﻿using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Hal.Zip.WPF.GUI
{
	/// <summary>
	/// Interaction logic for frmStatus.xaml
	/// </summary>
	public partial class frmStatus : Window
	{
		private string _sDirectoryToZip;
		public string DirectoryToZip
		{
			get { return _sDirectoryToZip; }
			set { _sDirectoryToZip = value; }
		}
		private string _sArchiveName;
		public string ArchiveName
		{
			get { return _sArchiveName; }
			set { _sArchiveName = value; }
		}
		private ZipFile _sArchiveToExpand;
		public ZipFile ArchiveToExpand
		{
			get { return _sArchiveToExpand; }
			set { _sArchiveToExpand = value; }
		}
		private string _sPassword;
		public string Password
		{
			get { return _sPassword; }
			set { _sPassword = value; }
		}

		public frmStatus()
		{
			InitializeComponent();
		}
		
		public void ZipDirectory()
		{
			BackgroundWorker zipFiles = new BackgroundWorker();
			zipFiles.WorkerReportsProgress = true;
			zipFiles.DoWork += (o, e) =>
			{
				using (ZipFile zip = new ZipFile())
				{
					if (_sPassword != string.Empty)
					{
						zip.Password = _sPassword;
						zip.Encryption = EncryptionAlgorithm.WinZipAes256;
					}

					zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
					zip.SaveProgress += zip_SaveProgress;
					zip.StatusMessageTextWriter = System.Console.Out;
					zip.AddDirectory(_sDirectoryToZip); // recurses subdirectories
					zip.Save(_sArchiveName);
				}
			};
			zipFiles.RunWorkerAsync();
		}

		void zip_SaveProgress(object sender, SaveProgressEventArgs e)
		{
			this.Dispatcher.Invoke(
				System.Windows.Threading.DispatcherPriority.Normal,
				new Action(
				delegate()
				{
					if (e.EventType == ZipProgressEventType.Saving_Started)
					{
						this.Title = e.ArchiveName;
						labelCompressionStatus.Text = "Saving: " + e.ArchiveName;
					}
					else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
					{
						labelCompressionStatus.Text = "Writing: " + e.CurrentEntry.FileName + " (" + (e.EntriesSaved + 1) + "/" + e.EntriesTotal + ")";
						progOverall.Maximum = e.EntriesTotal;
						progOverall.Value = e.EntriesSaved + 1;
					}
					else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead)
					{
						progCurrent.Value = (int)((e.BytesTransferred * 100) / e.TotalBytesToTransfer);
					}
					else if (e.EventType == ZipProgressEventType.Saving_Completed)
					{
						MessageBox.Show("Archive Created! It was saved here:\n\n" + e.ArchiveName);
						labelCompressionStatus.Text = "Your archive was saved here:  " + e.ArchiveName;
						btnClose.IsEnabled = true;
					}
				}
			));
		}

		public void ExpandDirectory(string zipToUnpack, string unpackDirectory)
		{
			BackgroundWorker expandDirectory = new BackgroundWorker();
			expandDirectory.WorkerReportsProgress = true;
			expandDirectory.DoWork += (o, e) =>
			{
				using (ZipFile zip = ZipFile.Read(zipToUnpack))
				{
					int step = Convert.ToInt32((double)zip.Count / 100.0);
					int percentComplete = 0;
					foreach (ZipEntry file in zip)
					{
						file.Extract(unpackDirectory, ExtractExistingFileAction.OverwriteSilently);
						percentComplete += step;
						expandDirectory.ReportProgress(percentComplete);
						zip.ExtractProgress += zip_ExtractProgress;
					}
				}
			};
			expandDirectory.RunWorkerAsync();
		}

		void zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
		{
			this.Dispatcher.Invoke(
				System.Windows.Threading.DispatcherPriority.Normal,
				new Action(
				delegate()
				{
					if (e.EventType == ZipProgressEventType.Saving_Started)
					{
						MessageBox.Show("Begin Saving: " + e.ArchiveName);
					}
					else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
					{
						labelCompressionStatus.Text = "Extracting: " + e.CurrentEntry.FileName + " (" + (e.EntriesExtracted + 1) + "/" + e.EntriesTotal + ")";
						progOverall.Maximum = e.EntriesTotal;
						progOverall.Value = e.EntriesExtracted + 1;
					}
					else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead)
					{
						progCurrent.Value = (int)((e.BytesTransferred * 100) / e.TotalBytesToTransfer);
					}
					else if (e.EventType == ZipProgressEventType.Saving_Completed)
					{
						MessageBox.Show("Archive Extracted! It was saved here:\n\n " + e.ArchiveName);
						labelCompressionStatus.Text = "Your directory is here:  " + e.ArchiveName;
						btnClose.IsEnabled = true;
					}
				}
			));
		}

		private void btnClose_Click(object sender, RoutedEventArgs e)
		{
			this.Close();
		}
	}
}